package com.qianniu.napi.common.util;

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class IdentifyingCode {

    public static final String VERIFY_CODE_KEY = "verify_code";//验证码长度
    /**
     * 验证码图片的宽度。
     */
    private int width = 120;
    /**
     * 验证码图片的高度。
     */
    private int height = 50;
    /**
     * 验证码的数量。
     */
    private Random random = new Random();

    public IdentifyingCode() {
    }

    /**
     * 生成随机颜色
     *
     * @param fc
     *            前景色
     * @param bc
     *            背景色
     * @return Color对象，此Color对象是RGB形式的。
     */
    private Color getRandomColor(int fc, int bc) {
        if (fc > 255) {
            fc = 200;
        }
        if (bc > 255) {
            bc = 255;
        }
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }

    /**
     * 绘制干扰线
     *
     * @param g
     *            Graphics2D对象，用来绘制图像
     * @param nums
     *            干扰线的条数
     */
    private void drawRandomLines(Graphics2D g, int nums) {
        for (int i = 0; i < nums; i++) {
            g.setColor(this.getRandomColor(120, 200));
            int x1 = random.nextInt(width);
            int y1 = random.nextInt(height);
            int x2 = random.nextInt(12);
            int y2 = random.nextInt(12);
            g.drawLine(x1, y1, x1 + x2, y1 + y2);
        }
    }

    /**
     * 获取随机字符串， 此函数可以产生由大小写字母，汉字，数字组成的字符串
     *
     * @return 随机字符串
     */
    private int drawRandomString(Graphics2D g) {
        int result = 0;
        // 定义字体样式
//        String[] arrFont = { "宋体", "黑体", "隶书", "楷体" };
        String[] arrFont = { "宋体" };
        Font myFont = new Font(arrFont[0], random.nextInt(4),26);
        // 设置字体
        g.setFont(myFont);
        int n = 0;
//		StringBuffer sbufTemp = new StringBuffer();
//		String[] arrOperations = { "加", "加上", "减", "减去", "乘", "乘以", "除以" };
        String[] arrOperations = {"加上", "减去", "乘以", "除以" };
//        String[] arrOperations = {"+", "-", "x", "/" };
//		String[] arrEnds = { "是？", "等于？" };
        String temp = "";
        int num1 = 0;
        int num2 = 0;
        String strOperation = "";
        // 第一个 数字
        num1 = random.nextInt(10);
        temp = String.valueOf(num1);
        writeStr(g, temp, n);
        n++;
//		sbufTemp.append(temp);

        // 第二个 运算符号
        strOperation = arrOperations[random.nextInt(arrOperations.length)];
        writeStr(g, strOperation.substring(0, 1), n);
        n++;
        if (strOperation.length() == 2) {
            writeStr(g, strOperation.substring(1, 2), n);
            n++;
        }
//		sbufTemp.append(strOperation);

        // 第三个 数字
        if (strOperation.contains("减")) {
            num2 = random.nextInt(num1 + 1);
        } else if (strOperation.contains("除")) {
            num2 = getRandomFactor(num1);
        } else {
            num2 = random.nextInt(10);
        }
        temp = String.valueOf(num2);
        writeStr(g, temp, n);
        n++;
//		sbufTemp.append(temp);

        // 第四个 结束语
//		temp = arrEnds[random.nextInt(2)];
//		writeStr(g, temp.substring(0, 1), n);
//		n++;
//		writeStr(g, temp.substring(1, 2), n);
//		n++;
//		if (temp.length() == 3)
//			writeStr(g, temp.substring(2, 3), n);
//
//		sbufTemp.append("等于");
        g.dispose();
        // 最后计算结果
        if (strOperation.contains("加")) {
            result = num1 + num2;
        } else if (strOperation.contains("减")) {
            result = num1 - num2;
        } else if (strOperation.contains("乘")) {
            result = num1 * num2;
        } else {
            result = num1 / num2;
        }

        return result;
    }

    /**
     * 随机获取一个因子数
     *
     * @param num
     * @return
     */
    private int getRandomFactor(int num) {
        if (num == 0) {
            return random.nextInt(8) + 1;
        }
        java.util.List<Integer> lstFactors = new ArrayList<Integer>();
        lstFactors.add(1);
        if (num % 2 == 0) {
            lstFactors.add(2);
        }
        if (num % 3 == 0) {
            lstFactors.add(3);
        }
        if (num % 4 == 0) {
            lstFactors.add(4);
        }
        lstFactors.add(num);

        return lstFactors.get(random.nextInt(lstFactors.size()));
    }

    private void writeStr(Graphics2D g, String temp, int i) {
        Color color = new Color(random.nextInt(100), random.nextInt(100),
                random.nextInt(100));
        g.setColor(color);
        // 每个字左右旋转90度以内的角度
        AffineTransform trans = new AffineTransform();
        if (random.nextInt(2) == 1) {
            trans.rotate(random.nextInt(90) * 3.14 / 180, 30 * i + 12, 27);
        } else {
            trans.rotate((random.nextInt(90) + 270) * 3.14 / 180, 30 * i + 12,
                    27);
        }
        g.setTransform(trans);
        g.drawString(temp, 30 * i + 10, 35);
    }

    /**
     * 绘制验证码主方法
     * @return list 0=图片流，1=验证码结果
     */
    public java.util.List drawIdentifyingCode() {
        java.util.List lst = new ArrayList();
        // 声明一个画布
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
        // 准备画笔
        Graphics2D g = image.createGraphics();
        g.setColor(getRandomColor(200, 250));
        // 绘制背景
        g.fillRect(0, 0, width, height);
        g.setColor(getRandomColor(180, 200));
        // 画干扰线
        drawRandomLines(g, 160);
        // 绘制验证码
        int result = drawRandomString(g);
        g.dispose();
        lst.add(image);
        lst.add(result);
//		try {
//			ImageIO.write(image, "JPEG", new File("d:/img/ic.jpg"));
//		} catch (IOException e) {
//			e.printStackTrace();
//		}
        return lst;
    }

    public static void main(String[] args) throws IOException {
        IdentifyingCode ic = new IdentifyingCode();

        List lst = ic.drawIdentifyingCode();
        System.out.println("验证码结果=" + lst.get(1));
        /**
         * 以下是验证码输出到浏览器的示例代码，仅供参考
         */
//		BufferedImage image = (BufferedImage)lst.get(0);
        // // 设置不缓存图片
        // response.setHeader("Pragma", "No-cache");
        // response.setHeader("Cache-Control", "No-cache");
        // response.setDateHeader("Expires", 0);
        // // 指定生成的相应图片
        // response.setContentType("image/jpeg");

        // ImageIO.write(image, "JPEG", response.getOutputStream()) ;
    }

}
